﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace PinWin
{
	class WindowsMessageHelper
	{
		/// <summary>
		/// Changes the size, position, and Z order of a child, pop-up or top-level window.
		/// </summary>
		/// <param name="hWnd">A handle to the window.</param>
		/// <param name="hWndInsertAfter">A handle to the window to precede the positioned window in the Z order. (HWND value)</param>
		/// <param name="X">The new position of the left side of the window, in client coordinates.</param>
		/// <param name="Y">The new position of the top of the window, in client coordinates.</param>
		/// <param name="W">The new width of the window, in pixels.</param>
		/// <param name="H">The new height of the window, in pixels.</param>
		/// <param name="uFlags">The window sizing and positioning flags. (SWP value)</param>
		/// <returns>Nonzero if function succeeds, zero if function fails.</returns>
		[DllImport("user32.dll", SetLastError = true)]
		public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int W, int H, uint uFlags);

		[System.Runtime.InteropServices.DllImport("user32.dll")]
		public static extern int BringWindowToTop(IntPtr hwnd);

		[DllImport("user32.dll")]
		[return: MarshalAs(UnmanagedType.Bool)]
		public static extern bool GetWindowRect(HandleRef hwnd, out RECT lpRect);

		[DllImport("user32.dll")]
		public static extern bool SetForegroundWindow(IntPtr hWnd);

		[DllImport("user32.dll")]
		public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);

		[DllImport("user32.dll")]
		public static extern bool IsIconic(IntPtr hWnd);

		[return: MarshalAs(UnmanagedType.Bool)]
		[DllImport("user32.dll", SetLastError = true)]
		public static extern bool GetWindowInfo(IntPtr hwnd, ref WINDOWINFO pwi);

		[DllImport("user32.dll", SetLastError = true)]
		public static extern int GetWindowLong(IntPtr hWnd, int nIndex);

		[DllImport("user32.dll")]
		public static extern bool SetLayeredWindowAttributes(IntPtr hwnd, uint crKey, byte bAlpha, uint dwFlags);

		[DllImport("user32.dll")]
		public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);


		[StructLayout(LayoutKind.Sequential)]
		public struct RECT
		{
			public int Left, Top, Right, Bottom;
			public RECT(int left, int top, int right, int bottom)
			{
				Left = left; Top = top; Right = right; Bottom = bottom;
			}
			public RECT(System.Drawing.Rectangle r) : this(r.Left, r.Top, r.Right, r.Bottom) { }
			public int X { get { return Left; } set { Right -= (Left - value); Left = value; } }
			public int Y { get { return Top; } set { Bottom -= (Top - value); Top = value; } }
			public int Height { get { return Bottom - Top; } set { Bottom = value + Top; } }
			public int Width { get { return Right - Left; } set { Right = value + Left; } }
			public static implicit operator System.Drawing.Rectangle(RECT r)
			{
				return new System.Drawing.Rectangle(r.Left, r.Top, r.Width, r.Height);
			}
			public static implicit operator RECT(System.Drawing.Rectangle r) { return new RECT(r); }
		}

		public const int WS_EX_LAYERED = 0x80000;
		public const int LWA_ALPHA = 0x2;

		[StructLayout(LayoutKind.Sequential)]
		public struct WINDOWINFO
		{
			public uint cbSize;
			public RECT rcWindow;
			public RECT rcClient;
			public uint dwStyle;
			public uint dwExStyle;
			public uint dwWindowStatus;
			public uint cxWindowBorders;
			public uint cyWindowBorders;
			public ushort atomWindowType;
			public ushort wCreatorVersion;

			public WINDOWINFO(Boolean? filler)
				: this()   // Allows automatic initialization of "cbSize" with "new WINDOWINFO(null/true/false)".
			{
				cbSize = (UInt32)(Marshal.SizeOf(typeof(WINDOWINFO)));
			}

		}

		/// <summary>
		/// HWND values for hWndInsertAfter
		/// </summary>
		public static class HWND
		{
			public static readonly IntPtr
			NOTOPMOST = new IntPtr(-2),
			BROADCAST = new IntPtr(0xffff),
			TOPMOST = new IntPtr(-1),
			TOP = new IntPtr(0),
			BOTTOM = new IntPtr(1);
		}



		/// <summary>
		/// SetWindowPos Flags
		/// </summary>
		public static class SWP
		{
			public static readonly int
			NOSIZE = 0x0001,
			NOMOVE = 0x0002,
			NOZORDER = 0x0004,
			NOREDRAW = 0x0008,
			NOACTIVATE = 0x0010,
			DRAWFRAME = 0x0020,
			FRAMECHANGED = 0x0020,
			SHOWWINDOW = 0x0040,
			HIDEWINDOW = 0x0080,
			NOCOPYBITS = 0x0100,
			NOOWNERZORDER = 0x0200,
			NOREPOSITION = 0x0200,
			NOSENDCHANGING = 0x0400,
			DEFERERASE = 0x2000,
			ASYNCWINDOWPOS = 0x4000;
		}

		public static readonly int
		SW_HIDE =            0,
		SW_SHOWNORMAL =      1,
		SW_NORMAL =          1,
		SW_SHOWMINIMIZED =   2,
		SW_SHOWMAXIMIZED =   3,
		SW_MAXIMIZE =        3,
		SW_SHOWNOACTIVATE =  4,
		SW_SHOW =            5,
		SW_MINIMIZE =        6,
		SW_SHOWMINNOACTIVE = 7,
		SW_SHOWNA =          8,
		SW_RESTORE =         9,
		SW_SHOWDEFAULT =     10,
		SW_FORCEMINIMIZE =   11,
		SW_MAX =             11;
		
		[DllImport("user32.dll", CharSet = CharSet.Auto)]
		private static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);

		[DllImport("user32.dll")]
		public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

		[DllImport("user32.dll")]
		public static extern int RegisterWindowMessage(string msgName);

		public static int ClearHistoryArg;
		public static int SetOnTopArg;

		static WindowsMessageHelper()
		{
			ClearHistoryArg = WindowsMessageHelper.RegisterWindowMessage("Jumplist.demo.ClearHistoryArg");
			SetOnTopArg = WindowsMessageHelper.RegisterWindowMessage("Jumplist.demo.SetOnTopArg");
		}

		public static int RegisterMessage(string msgName)
		{
			return RegisterWindowMessage(msgName);
		}

		public static void SendMessage(string windowTitle, int msgId)
		{
			SendMessage(windowTitle, msgId, IntPtr.Zero, IntPtr.Zero);
		}

		public static bool SendMessage(string windowTitle, int msgId, IntPtr wParam, IntPtr lParam)
		{
			IntPtr WindowToFind = FindWindow(null, windowTitle);
			if (WindowToFind == IntPtr.Zero) return false;

			long result = SendMessage(WindowToFind, msgId, wParam, lParam);

			if (result == 0) return true;
			else return false;
		}


		// P/Invoke constants
		public const int WM_SYSCOMMAND = 0x112;
		public const int MF_STRING = 0x0;
		public const int MF_SEPARATOR = 0x800;

		// P/Invoke declarations
		[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
		public static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);

		[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
		public static extern bool AppendMenu(IntPtr hMenu, int uFlags, int uIDNewItem, string lpNewItem);

		[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
		public static extern bool InsertMenu(IntPtr hMenu, int uPosition, int uFlags, int uIDNewItem, string lpNewItem);


		// ID for the About item on the system menu
		public static int SYSMENU_TOP = 0x111;

		[DllImport("user32.dll")]
		public static extern bool GetMenuItemInfo(IntPtr hMenu, uint uItem, bool fByPosition, ref MENUITEMINFO lpmii);

		[DllImport("User32")]
		public static extern int GetMenuItemCount(IntPtr hWnd);

		[StructLayout(LayoutKind.Sequential)]
		public struct MENUITEMINFO
		{
			public uint cbSize;
			public uint fMask;
			public uint fType;
			public uint fState;
			public uint wID;
			public IntPtr hSubMenu;
			public IntPtr hbmpChecked;
			public IntPtr hbmpUnchecked;
			public string dwTypeData;
			public IntPtr dwItemData;
			public uint cch;
			public IntPtr hbmpItem;
		}

		public abstract class WindowStyles
		{
			public const uint WS_OVERLAPPED = 0x00000000;
			public const uint WS_POPUP = 0x80000000;
			public const uint WS_CHILD = 0x40000000;
			public const uint WS_MINIMIZE = 0x20000000;
			public const uint WS_VISIBLE = 0x10000000;
			public const uint WS_DISABLED = 0x08000000;
			public const uint WS_CLIPSIBLINGS = 0x04000000;
			public const uint WS_CLIPCHILDREN = 0x02000000;
			public const uint WS_MAXIMIZE = 0x01000000;
			public const uint WS_CAPTION = 0x00C00000;     /* WS_BORDER | WS_DLGFRAME  */
			public const uint WS_BORDER = 0x00800000;
			public const uint WS_DLGFRAME = 0x00400000;
			public const uint WS_VSCROLL = 0x00200000;
			public const uint WS_HSCROLL = 0x00100000;
			public const uint WS_SYSMENU = 0x00080000;
			public const uint WS_THICKFRAME = 0x00040000;
			public const uint WS_GROUP = 0x00020000;
			public const uint WS_TABSTOP = 0x00010000;

			public const uint WS_MINIMIZEBOX = 0x00020000;
			public const uint WS_MAXIMIZEBOX = 0x00010000;

			public const uint WS_TILED = WS_OVERLAPPED;
			public const uint WS_ICONIC = WS_MINIMIZE;
			public const uint WS_SIZEBOX = WS_THICKFRAME;
			public const uint WS_TILEDWINDOW = WS_OVERLAPPEDWINDOW;

			// Common Window Styles

			public const uint WS_OVERLAPPEDWINDOW =
				(WS_OVERLAPPED |
				  WS_CAPTION |
				  WS_SYSMENU |
				  WS_THICKFRAME |
				  WS_MINIMIZEBOX |
				  WS_MAXIMIZEBOX);

			public const uint WS_POPUPWINDOW =
				(WS_POPUP |
				  WS_BORDER |
				  WS_SYSMENU);

			public const uint WS_CHILDWINDOW = WS_CHILD;

			//Extended Window Styles

			public const uint WS_EX_DLGMODALFRAME = 0x00000001;
			public const uint WS_EX_NOPARENTNOTIFY = 0x00000004;
			public const uint WS_EX_TOPMOST = 0x00000008;
			public const uint WS_EX_ACCEPTFILES = 0x00000010;
			public const uint WS_EX_TRANSPARENT = 0x00000020;

			//#if(WINVER >= 0x0400)
			public const uint WS_EX_MDICHILD = 0x00000040;
			public const uint WS_EX_TOOLWINDOW = 0x00000080;
			public const uint WS_EX_WINDOWEDGE = 0x00000100;
			public const uint WS_EX_CLIENTEDGE = 0x00000200;
			public const uint WS_EX_CONTEXTHELP = 0x00000400;

			public const uint WS_EX_RIGHT = 0x00001000;
			public const uint WS_EX_LEFT = 0x00000000;
			public const uint WS_EX_RTLREADING = 0x00002000;
			public const uint WS_EX_LTRREADING = 0x00000000;
			public const uint WS_EX_LEFTSCROLLBAR = 0x00004000;
			public const uint WS_EX_RIGHTSCROLLBAR = 0x00000000;

			public const uint WS_EX_CONTROLPARENT = 0x00010000;
			public const uint WS_EX_STATICEDGE = 0x00020000;
			public const uint WS_EX_APPWINDOW = 0x00040000;

			public const uint WS_EX_OVERLAPPEDWINDOW = (WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE);
			public const uint WS_EX_PALETTEWINDOW = (WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST);
			//#endif /* WINVER >= 0x0400 */

			//#if(_WIN32_WINNT >= 0x0500)
			public const uint WS_EX_LAYERED = 0x00080000;
			//#endif /* _WIN32_WINNT >= 0x0500 */

			//#if(WINVER >= 0x0500)
			public const uint WS_EX_NOINHERITLAYOUT = 0x00100000; // Disable inheritence of mirroring by children
			public const uint WS_EX_LAYOUTRTL = 0x00400000; // Right to left mirroring
			//#endif /* WINVER >= 0x0500 */

			//#if(_WIN32_WINNT >= 0x0500)
			public const uint WS_EX_COMPOSITED = 0x02000000;
			public const uint WS_EX_NOACTIVATE = 0x08000000;
			//#endif /* _WIN32_WINNT >= 0x0500 */
		}

		public const int GWL_WNDPROC = (-4);

		public const int GWL_HINSTANCE = (-6);

		public const int GWL_HWNDPARENT = (-8);

		public const int GWL_STYLE = (-16);

		public const int GWL_EXSTYLE = (-20);

		public const int GWL_USERDATA = (-21);

		public const int GWL_ID = (-12);
	}
}
